home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / ABUSESRC.ZIP / AbuseSrc / imlib / port / aix_orig / gen_drv.c < prev    next >
C/C++ Source or Header  |  1996-07-25  |  8KB  |  335 lines

  1.  
  2. #define NUM_CHANNELS 8
  3. #define STDOUT_FD driver_out_fd
  4. #define STDIN_FD  driver_in_fd
  5.  
  6.  
  7.  
  8. #define DOUT_NAME  "/tmp/sfxdrv.signal"
  9. #define DIN_NAME "/tmp/sfxdrv.command"
  10.  
  11.  
  12. enum { SFXCMD_QUIT,
  13.        SFXCMD_REGISTER,
  14.        SFXCMD_UNREGISTER,
  15.        SFXCMD_PLAY
  16.      };
  17.  
  18. typedef struct sfx_handle_s sfx_handle;
  19.  
  20. struct sfx_handle_s
  21. {
  22.   int          shm_id; 
  23.   void         *shm_data_pointer;
  24.   sfx_handle   *next;  
  25.   long         size;
  26.   int          use_count;
  27. };
  28.  
  29. int driver_out_fd,driver_in_fd;
  30. sfx_handle *sfx_list=NULL;
  31.  
  32.  
  33.  
  34. #define TOTAL_SIGS 29
  35.  
  36. int sigs[TOTAL_SIGS]={SIGHUP,SIGINT,SIGQUIT,SIGILL,SIGTRAP,
  37.               SIGABRT,SIGIOT,SIGBUS,SIGFPE,SIGKILL,
  38.               SIGUSR1,SIGSEGV,SIGUSR2,SIGPIPE,SIGALRM,
  39.               SIGTERM,SIGCHLD,SIGCONT,SIGSTOP,
  40.               SIGTSTP,SIGTTIN,SIGTTOU,SIGIO,
  41.               SIGURG,SIGXCPU,SIGXFSZ,SIGVTALRM,SIGPROF,
  42.               SIGWINCH};
  43.  
  44. struct channel
  45. {
  46.   unsigned char *data;         // next data to be qued
  47.   long left;                   // how much is left to play?  
  48.   unsigned char volume;        // indexed into volume table
  49.   unsigned long add_time;      // time at which the channel started playing
  50.   sfx_handle *snd;             // pointer to actual sound, so delete can stop us if need be
  51. } channels[NUM_CHANNELS];
  52.  
  53. #define uchar unsigned char
  54. short buf[BUF_SIZE];   // mixing buffer
  55.  
  56. // add a new sound effect into the channel list, if no free channel
  57. // oldest gets replaced with new sound
  58. void play(sfx_handle *snd, unsigned char volume)
  59. {
  60.   int i,free_channel=-1;
  61.   unsigned long oldest_channel=0,
  62.                 oldest_channel_time=10000,
  63.                 newest_channel_time=0;
  64.  
  65.   for (i=0;i<NUM_CHANNELS;i++)
  66.   {
  67.     if (channels[i].data)
  68.     { 
  69.       int my_time=channels[i].add_time;
  70.       if (my_time<oldest_channel_time)
  71.       {
  72.     oldest_channel=i;
  73.     oldest_channel_time=my_time;
  74.       }
  75.       if (my_time>newest_channel_time)
  76.     newest_channel_time=my_time;
  77.     } else free_channel=i;
  78.   }
  79.   
  80.   if (free_channel==-1)
  81.     free_channel=oldest_channel;
  82.  
  83.   channels[free_channel].snd=snd;
  84.   channels[free_channel].add_time=newest_channel_time+1;
  85.   channels[free_channel].data=(uchar *)snd->shm_data_pointer;
  86.   channels[free_channel].left=snd->size;
  87.   channels[free_channel].volume=volume*32/128;
  88. //  fprintf(stderr, "vol=%d\n", channels[free_channel].volume);
  89. }
  90.  
  91.  
  92. int output_sounds()  // return 0 if no sounds to ouput
  93. {
  94.   unsigned char *s;
  95.   int i,j;
  96.   unsigned char *data;
  97.   
  98.   int run_size;
  99.   memset(buf,0,sizeof buf);
  100.   for (j=0;j<NUM_CHANNELS;j++)
  101.   {
  102.     data = channels[j].data;
  103.     if (data)
  104.     {
  105.       if (channels[j].left<=BUF_SIZE)    // handle imminent channel death
  106.       {
  107.         run_size=channels[j].left;
  108.         channels[j].data = NULL;
  109.       }
  110.       else
  111.       {
  112.         run_size=BUF_SIZE;
  113.         channels[j].data += BUF_SIZE;
  114.       }
  115.       channels[j].left -= BUF_SIZE;
  116.       
  117.       // add the chanels together into an int
  118.       // reserve the clip and scale to proper 16-bit for the output step
  119.       for (i=0;i<run_size;i++)
  120.         buf[i] += ((short)data[i] - 128) * channels[j].volume;
  121.  
  122.     }
  123.   }
  124.  
  125.   output_samples(buf);
  126.  
  127.   return 1;    // always say we have something, we will do blanks if nothing else
  128.  
  129. }
  130.  
  131.  
  132.  
  133. #ifdef __sgi
  134. void clean_up(...)
  135. #else
  136. void clean_up(int why)      // on exit unattach all shared memory links
  137. #endif
  138. {  
  139.   sfx_handle *last;
  140.   while (sfx_list)
  141.   {
  142.     shmdt((char *)sfx_list->shm_data_pointer);
  143.     if (shmctl(sfx_list->shm_id,IPC_RMID,NULL)!=0)
  144.       printf("shmctl failed, why?\n");
  145.     last=sfx_list;
  146.     sfx_list=sfx_list->next;
  147.     free(last);
  148.   }
  149.   sound_uninit();
  150.   unlink(DIN_NAME);
  151.   unlink(DOUT_NAME);
  152. }
  153.  
  154. void die()
  155. { clean_up(0);
  156.   exit(0);
  157. }
  158.  
  159.  
  160. static int sound_fd_ready_to_read(int fd)
  161. {
  162.   struct timeval tv={0,0};
  163.   fd_set kbd_set,ex_set;
  164.   FD_ZERO(&kbd_set);
  165.   FD_SET(fd,&kbd_set);
  166.   memcpy((void *)&ex_set,(void *)&kbd_set,sizeof(ex_set));
  167.   select(FD_SETSIZE,&kbd_set,NULL,&ex_set,&tv);                // check for exception
  168.   if (FD_ISSET(fd,&ex_set))
  169.     die();
  170.   return (FD_ISSET(fd,&kbd_set));
  171. }
  172.  
  173.  
  174. void sound_watch()
  175. {
  176.  
  177.   sfx_handle *sfx;
  178.  
  179.   while (1)
  180.   {
  181.     while (sound_fd_ready_to_read(STDIN_FD))
  182.     {
  183.       uchar cmd;
  184.             int rc;
  185.       if ((rc=read(STDIN_FD,&cmd,1))!=1)
  186.       { die(); }
  187.           fprintf(stderr,"recv'd %d bytes\n", rc);
  188.       switch (cmd)
  189.       {
  190.     case SFXCMD_REGISTER :
  191.     {
  192.       int shm_id;
  193.       long size;
  194.       uchar return_code;
  195.       if (read(STDIN_FD,&shm_id,sizeof(shm_id))!=sizeof(shm_id))
  196.       { fprintf(stderr,"sndrv er1\n"); die(); }
  197.       if (read(STDIN_FD,&size,sizeof(size))!=sizeof(size))
  198.       { fprintf(stderr,"sndrv er2\n"); die(); }
  199.  
  200.       sfx=malloc(sizeof(sfx_handle));
  201.       sfx->shm_id=shm_id;
  202.       sfx->shm_data_pointer=shmat(shm_id,NULL,0);
  203.       if (!sfx->shm_data_pointer)
  204.       { fprintf(stderr,"Sound driver : unable to attach shared memory segment\n"); die(); }
  205.       sfx->size=size;
  206.       sfx->use_count=0;
  207.       sfx->next=sfx_list;
  208.       sfx_list=sfx;
  209.           
  210.         fprintf(stderr,"registered %d %d\n", shm_id, size);
  211.  
  212.       cmd=1;
  213.       if (write(STDOUT_FD,&cmd,sizeof(cmd))!=sizeof(cmd))
  214.       { fprintf(stderr,"sndrv er3\n"); die(); }
  215.  
  216.     } break;
  217.     case SFXCMD_UNREGISTER :
  218.     {
  219.       int shm_id,i;
  220.       sfx_handle *f,*find=NULL,*last_find=NULL;
  221.       if (read(STDIN_FD,&shm_id,sizeof(shm_id))!=sizeof(shm_id))
  222.       { die(); }
  223.       for (f=sfx_list;f && !find;f=f->next)   // see if we can find the shm id in list
  224.       {
  225.         if (f->shm_id==shm_id)
  226.           find=f;
  227.         last_find=find;         // svae last link so we can remove from the list
  228.       }
  229.       
  230.       if (find)
  231.       {
  232.         // see if there are any sound channels playing this sound, if so stop them because
  233.         // memory is fixing to be deleted
  234.         for (i=0;i<NUM_CHANNELS;i++)
  235.         {
  236.           if (channels[i].snd==find)
  237.             channels[i].data=NULL;
  238.         }
  239.         // now free the memory
  240.         shmdt((char *)find->shm_data_pointer);          // detach and remove shm
  241.         if (last_find) 
  242.           last_find->next=find->next;           // unlink from sound list
  243.         else
  244.           sfx_list=sfx_list->next;
  245.       } else { fprintf(stderr,"Attempt to remove unknown sound effect\n"); die(); }
  246.     } break;
  247.  
  248.     case SFXCMD_PLAY :
  249.     {
  250.       int shm_id,i,volume;
  251.       sfx_handle *f;
  252.       if (read(STDIN_FD,&shm_id,sizeof(shm_id))!=sizeof(shm_id))
  253.         die();
  254.       if (read(STDIN_FD,&volume,sizeof(volume))!=sizeof(volume))
  255.         die();
  256.       for (f=sfx_list;f && f->shm_id!=shm_id;f=f->next);
  257.       if (f)
  258.         play(f,volume);
  259.       else fprintf(stderr,"sound driver : bad id to play\n");
  260. //        fprintf(stderr, "play %d %d \n", shm_id, volume);
  261.     } break;
  262.     default :     // die on unknown or DIE command
  263.     { die(); }
  264.       } 
  265.     }
  266.     output_sounds();
  267.   }
  268. }
  269.  
  270.  
  271. main()
  272. {
  273.  
  274.     int i;
  275.     uchar success;
  276. /*
  277.     int chd;
  278.   chd=fork();
  279.   if (chd)
  280.   {
  281.     printf("%d\n",chd);         // tell parent the sound driver's process number
  282.     return 0;
  283.   }
  284. */
  285.     printf("%d\n",getpid());         // tell parent the sound driver's process number
  286.     fclose(stdout);
  287.  
  288.   success=sound_init();    // initailize sound and send status to who ever ran us.
  289.   if (!success)
  290.   {
  291.     printf("-1");
  292.     return 0;
  293.   }
  294.  
  295.   unlink(DIN_NAME);
  296.   unlink(DOUT_NAME);
  297.  
  298. //  int old_mask=umask(S_IRWXU | S_IRWXG | S_IRWXO);
  299.   if (mkfifo(DIN_NAME,S_IRWXU | S_IRWXG | S_IRWXO))
  300.   { perror("Sound driver : unable to make fifo in /tmp");
  301.     return 0;
  302.   }
  303.   chmod(DIN_NAME,S_IRWXU | S_IRWXG | S_IRWXO);
  304.  
  305.   if (mkfifo(DOUT_NAME,S_IRWXU | S_IRWXG | S_IRWXO))
  306.   { perror("Sound driver : unable to make fifo in /tmp");
  307.     return 0;
  308.   }
  309.  
  310.   chmod(DOUT_NAME,S_IRWXU | S_IRWXG | S_IRWXO);
  311.   //umask(old_mask);
  312.  
  313.   driver_out_fd=open(DOUT_NAME,O_RDWR);
  314.   if (driver_out_fd<0)
  315.   { perror(DOUT_NAME); 
  316.     exit(1);
  317.   }
  318.  
  319.   driver_in_fd=open(DIN_NAME,O_RDWR);
  320.   if (driver_in_fd<0)
  321.   { perror(DIN_NAME); 
  322.     exit(1);
  323.   }
  324.  
  325.   for (i=0;i<TOTAL_SIGS;i++)
  326.     signal(sigs[i],clean_up);
  327.  
  328.   sound_watch();
  329.  
  330.   return 0;
  331. }
  332.  
  333.  
  334.  
  335.